package net.godcode.olivenotes.services;

import net.godcode.olivenotes.entities.EntityInterceptor;
import net.godcode.olivenotes.entities.PostDAO;
import net.godcode.olivenotes.entities.PostDAOHibernate;
import net.godcode.olivenotes.entities.RoleDAO;
import net.godcode.olivenotes.entities.RoleDAOHibernate;
import net.godcode.olivenotes.entities.Tag;
import net.godcode.olivenotes.entities.TagDAO;
import net.godcode.olivenotes.entities.TagDAOHibernate;
import net.godcode.olivenotes.entities.UserDAO;
import net.godcode.olivenotes.entities.UserDAOHibernate;
import net.godcode.olivenotes.services.security.SecurityModule;
import net.godcode.t5c.flickr.services.OliveNotesFlickrModule;

import org.apache.tapestry.TapestryConstants;
import org.apache.tapestry.hibernate.HibernateConfigurer;
import org.apache.tapestry.internal.services.ResourceCache;
import org.apache.tapestry.internal.services.ResourceStreamer;
import org.apache.tapestry.ioc.MappedConfiguration;
import org.apache.tapestry.ioc.OrderedConfiguration;
import org.apache.tapestry.ioc.ServiceBinder;
import org.apache.tapestry.ioc.annotations.Inject;
import org.apache.tapestry.ioc.annotations.InjectService;
import org.apache.tapestry.ioc.annotations.SubModule;
import org.apache.tapestry.services.ClasspathAssetAliasManager;
import org.apache.tapestry.services.ComponentClassResolver;
import org.apache.tapestry.services.Dispatcher;
import org.apache.tapestry.services.PageRenderRequestHandler;
import org.apache.tapestry.services.Request;
import org.apache.tapestry.services.RequestGlobals;
import org.hibernate.Session;
import org.hibernate.cfg.Configuration;
import org.slf4j.LoggerFactory;

@SubModule({ SecurityModule.class, OliveNotesFlickrModule.class })
/**
 * The IoC module for OliveNotes.
 * 
 * @author Chris Lewis Dec 26, 2007 <chris@thegodcode.net>
 * @version $Id: OliveNotesModule.java 35 2008-01-24 14:51:13Z burningodzilla $
 */
public class OliveNotesModule {

	public static void bind(ServiceBinder binder) {
		
		//DAO bindings.
		binder.bind(PostDAO.class, PostDAOHibernate.class);
		binder.bind(TagDAO.class, TagDAOHibernate.class);
		binder.bind(UserDAO.class, UserDAOHibernate.class);
		binder.bind(RoleDAO.class, RoleDAOHibernate.class);
				
	}
	
	/**
	 * Build a quick TagSplitter for comma-delimited string lists.
	 * @return The TagSplitter.
	 */
	public static TagSplitter buildTagSplitter() {
		return new TagSplitter() {
			
			public Tag[] split(String sTags) {
				String[] splitTags = sTags.split(",");
				//TODO should return null if none... check
				Tag[] tags = new Tag[splitTags.length];
				for(int i = 0; i < splitTags.length; i++) {
					tags[i] = new Tag(splitTags[i].trim());
				}
				return tags;
			}
			
			public String[] splitAsStrings(String tags) {
				//TODO should return null if none... check
				String[] _tags = tags.split(",");
				for(int i = 0; i < _tags.length; i++) {
					_tags[i] = _tags[i].trim();
				}
				return _tags;
			}
		};
	}
	
	/* Contributions. */
	
	public static void contributeApplicationDefaults(MappedConfiguration<String, String> configuration) {
		
		/* Context-provided paths and resources. */
		configuration.add("js.root", "context:js");
		
		/* Application image resources. */
		configuration.add("images.root", "context:img");
		configuration.add("images.olive-notes", "${images.root}/olive-notes.gif");
		
		configuration.add("blog.uploads.images-fixme", "img/blog/uploads");
		
		/*
		 * Application theming symbols. The application's look and feel is controlled primarily
		 * by CSS. These symbols are combined into the final symbol ${theme.default}.
		 */
		configuration.add("theme.root", "context:themes");
		configuration.add("theme.core-file", "theme.css");
		configuration.add("theme.default-name", "default");
		configuration.add("theme.default", "${theme.root}/${theme.default-name}/${theme.core-file}");
		
		//configuration.add("flickr.test", "THIS IS A TEAST");
		
		/*
		 * Framework configurations.
		 */
		configuration.add("tapestry.supported-locales", "en");
		configuration.add(TapestryConstants.PRODUCTION_MODE_SYMBOL, "false"); //tapestry.production-mode
	}
	
	/**
	 * TODO need configs??
	 * Configure the access controller.
	 * @param configuration
	 */
	public void contributeAccessController(MappedConfiguration<String, String> configuration) {
		configuration.add("test", "test-value");
	}
	
	/**
	 * Contribute an AccessController to the MasterDispatcher.
	 * 
	 * {@link org.apache.tapestry.services.TapestryModule#contributeMasterDispatcher(OrderedConfiguration,
	 * ClasspathAssetAliasManager, ResourceCache, ResourceStreamer, PageRenderRequestHandler,
	 * ComponentActionRequestHandler, ComponentClassResolver, String)}
	 */
	public void contributeMasterDispatcher(OrderedConfiguration<Dispatcher> configuration,
		@InjectService("AccessController") Dispatcher accessControl) {
		configuration.add("AccessController", accessControl, "before:PageRender");
	}
	
	/**
	 * Hibernate configurations.
	 * @param config
	 * @param session
	 */
	public static void contributeHibernateSessionSource(
		OrderedConfiguration<HibernateConfigurer> config,
		final Session session) {
		
		config.add("HibernateConfiguration", new HibernateConfigurer() {
			public void configure(Configuration configuration) {
				/*
				 * I'm having trouble getting a reference to an implementation at the moment,
				 * so we'll settle on this for the moment.
				 */
				configuration.setInterceptor(new EntityInterceptor(session,
					LoggerFactory.getLogger(EntityInterceptor.class)));
			}
		});
	}
	
}